package com.yu.demo.user.infrastructure.persistence.repository;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yu.demo.user.domain.entity.User;
import com.yu.demo.user.domain.repository.UserRepository;
import com.yu.demo.user.domain.valueobject.*;
import com.yu.demo.user.infrastructure.persistence.entity.UserPO;
import com.yu.demo.user.infrastructure.persistence.mapper.UserMapper;
import org.springframework.stereotype.Repository;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户仓储实现
 * 实现领域仓储接口，处理数据持久化
 */
@Repository
public class UserRepositoryImpl implements UserRepository {
    
    private final UserMapper userMapper;
    
    public UserRepositoryImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
    
    @Override
    public User save(User user) {
        UserPO userPO = toPO(user);
        if (user.getId() == null) {
            // 新增用户
            userMapper.insert(userPO);
            return toDomain(userPO);
        } else {
            // 更新用户
            userMapper.updateById(userPO);
            return toDomain(userPO);
        }
    }
    
    @Override
    public Optional<User> findById(UserId id) {
        UserPO userPO = userMapper.selectById(id.getValue());
        return userPO != null ? Optional.of(toDomain(userPO)) : Optional.empty();
    }
    
    @Override
    public Optional<User> findByUsername(Username username) {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username.getValue());
        UserPO userPO = userMapper.selectOne(queryWrapper);
        return userPO != null ? Optional.of(toDomain(userPO)) : Optional.empty();
    }
    
    @Override
    public Optional<User> findByEmail(Email email) {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email.getValue());
        UserPO userPO = userMapper.selectOne(queryWrapper);
        return userPO != null ? Optional.of(toDomain(userPO)) : Optional.empty();
    }
    
    @Override
    public List<User> findAll() {
        List<UserPO> userPOs = userMapper.selectList(null);
        return userPOs.stream()
                .map(this::toDomain)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<User> findAllActive() {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_active", true);
        List<UserPO> userPOs = userMapper.selectList(queryWrapper);
        return userPOs.stream()
                .map(this::toDomain)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<User> findByRole(String role) {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role", role);
        List<UserPO> userPOs = userMapper.selectList(queryWrapper);
        return userPOs.stream()
                .map(this::toDomain)
                .collect(Collectors.toList());
    }
    
    @Override
    public void delete(UserId id) {
        userMapper.deleteById(id.getValue());
    }
    
    @Override
    public boolean existsByUsername(Username username) {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username.getValue());
        return userMapper.selectCount(queryWrapper) > 0;
    }
    
    @Override
    public boolean existsByEmail(Email email) {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email.getValue());
        return userMapper.selectCount(queryWrapper) > 0;
    }
    
    @Override
    public long count() {
        return userMapper.selectCount(null);
    }
    
    @Override
    public long countActive() {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_active", true);
        return userMapper.selectCount(queryWrapper);
    }
    
    /**
     * 领域实体转换为持久化实体
     */
    private UserPO toPO(User user) {
        UserPO userPO = new UserPO();
        if (user.getId() != null) {
            userPO.setId(user.getId().getValue());
        }
        userPO.setUsername(user.getUsername().getValue());
        userPO.setEmail(user.getEmail().getValue());
        userPO.setPasswordHash(user.getPasswordHash().getValue());
        userPO.setRole(user.getRole().getValue());
        userPO.setIsActive(user.isActiveUser());
        
        // 转换时间
        if (user.getCreatedAt() != null) {
            userPO.setCreatedAt(Timestamp.from(user.getCreatedAt().atZone(ZoneId.systemDefault()).toInstant()));
        }
        if (user.getUpdatedAt() != null) {
            userPO.setUpdatedAt(Timestamp.from(user.getUpdatedAt().atZone(ZoneId.systemDefault()).toInstant()));
        }
        if (user.getLastLogin() != null) {
            userPO.setLastLogin(Timestamp.from(user.getLastLogin().atZone(ZoneId.systemDefault()).toInstant()));
        }
        
        return userPO;
    }
    
    /**
     * 持久化实体转换为领域实体
     */
    private User toDomain(UserPO userPO) {
        return User.reconstruct(
            new UserId(userPO.getId()),
            new Username(userPO.getUsername()),
            new Email(userPO.getEmail()),
            new PasswordHash(userPO.getPasswordHash()),
            new UserRole(userPO.getRole()),
            userPO.getIsActive(),
            userPO.getCreatedAt() != null ? 
                userPO.getCreatedAt().toLocalDateTime() : null,
            userPO.getUpdatedAt() != null ? 
                userPO.getUpdatedAt().toLocalDateTime() : null,
            userPO.getLastLogin() != null ? 
                userPO.getLastLogin().toLocalDateTime() : null
        );
    }
}
